package com.unicampmaps;

import java.io.IOException;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.preference.PreferenceManager;

public class DatabaseUpdater extends AsyncTask<String, Void, Boolean> {
	final static int TIMEOUT = 10;
	final static String URI_LAST_UPDATED = "http://www.students.ic.unicamp.br/~ra104864/unicampmaps/last_updated.txt";
	final static String URI = "http://www.students.ic.unicamp.br/~ra104864/unicampmaps/venues.php";
	private Context mContext;
	private SQLiteDatabase db;
	
	public DatabaseUpdater(Context c, SQLiteDatabase db) {
		super();

		this.mContext = c;
		this.db = db;
	}

	@Override
	protected Boolean doInBackground(String... urls) {
		System.out.println("doInBackground");
		if (this.isOnline()) {
			System.out.println("ONLINE");
			this.updateDatabase();
			return Boolean.TRUE;
		} else {
			System.out.println("OFFLINE");
			return Boolean.FALSE;	
		}
    }

    protected void onProgressUpdate(Integer... progress) {
        //setProgressPercent(progress[0]);
    }

    protected void onPostExecute(Long result) {
        //showDialog("Downloaded " + result + " bytes");
    }
	
    public boolean isOnline() {
        ConnectivityManager cm = (ConnectivityManager) this.mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnectedOrConnecting()) {
            return true;
        }
        return false;
    }
    
	private DefaultHttpClient createHttpClient() {
		final SchemeRegistry supportedSchemes = new SchemeRegistry();
		
		supportedSchemes.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
		supportedSchemes.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
		
		final HttpParams params = new BasicHttpParams();
		
		HttpConnectionParams.setConnectionTimeout(params, DatabaseUpdater.TIMEOUT*1000);
		HttpConnectionParams.setSoTimeout(params, DatabaseUpdater.TIMEOUT*1000);
		HttpConnectionParams.setSocketBufferSize(params, 8192);
		
		HttpClientParams.setRedirecting(params, false);
		
		final ClientConnectionManager com = new ThreadSafeClientConnManager(params, supportedSchemes);
		
		return new DefaultHttpClient(com, params);
	}
	
	private long getDatabaseVersion() {
		HttpGet httpGet = new HttpGet(DatabaseUpdater.URI_LAST_UPDATED);
		
		DefaultHttpClient httpClient = createHttpClient();
		System.out.println("GETDATABASE");
		
		HttpResponse httpResponse;
		try {
			httpResponse = httpClient.execute(httpGet);
			String response = EntityUtils.toString(httpResponse.getEntity());

			return Long.parseLong(response);
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			System.out.println("EXCEÇÃO1");
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("EXCEÇÃO1");
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 0;
	}
	
	private String getDatabaseJSON() {
		long starttime = 0;
		HttpGet httpGet = new HttpGet(DatabaseUpdater.URI + "?starttime=" + starttime);
		
		DefaultHttpClient httpClient = createHttpClient();
		System.out.println("GETDATABASE");
		
		HttpResponse httpResponse;
		try {
			httpResponse = httpClient.execute(httpGet);
			String response = EntityUtils.toString(httpResponse.getEntity());

			return response;
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			System.out.println("EXCEÇÃO1");
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("EXCEÇÃO1");
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "";
	}
	
	private void updateDatabase() {
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this.mContext);
		Editor edit = prefs.edit();
		long externalTimestamp = getDatabaseVersion();
		long internalTimestamp = prefs.getLong("dbVersion", 0);
		if (externalTimestamp <= internalTimestamp) {
			return;
		}
		
		String json = getDatabaseJSON();
		
		try {
			JSONArray jsonArr = new JSONArray(json);
			
			 if (jsonArr != null) {
                 int lenght = jsonArr.length();
                 
                 for (int i = 0; i < lenght; i++) {
                	 JSONObject jsonObj = jsonArr.getJSONObject(i);
                	 
                	 //Por precaução testamos se o ID da venue já existe, se existir não realiza o INSERT
                	 String[] projection = { VenueData.C_ID };
                	 String where =  VenueData.C_ID + "= " + jsonObj.getLong(VenueData.C_ID);
                	 Cursor cursor = db.query(VenueData.TABLE, projection, where, null, null, null, null, null);
             		
                	 if (cursor != null) {
             			cursor.moveToFirst();
             			if (cursor.getCount() == 0) {
             				//Tudo OK, insere o registro no banco de dados atual
             				String query = "INSERT INTO " + VenueData.TABLE + " (" + 
									VenueData.C_ID + ", " +
									VenueData.C_FOURSQUARE_VENUE_ID + ", " + 
									VenueData.C_TYPE + ", " + 
									VenueData.C_NAME + ", " +
									VenueData.C_ABBR + ", " + 
									VenueData.C_ADDRESS + ", " + 
									VenueData.C_LATITUDE + ", " +
									VenueData.C_LONGITUDE + ", " +
									VenueData.C_PHONE_NUMBER + ", " +
									VenueData.C_SITE + ", " +
									VenueData.C_IMAGE + ")  " +				
									"SELECT " + jsonObj.getLong(VenueData.C_ID) + ", '" + 
									jsonObj.getString(VenueData.C_FOURSQUARE_VENUE_ID) + "', " +
									jsonObj.getInt(VenueData.C_TYPE) + ", '" +
									jsonObj.getString(VenueData.C_NAME) + "', '" +
									jsonObj.getString(VenueData.C_ABBR) + "', '" +
									jsonObj.getString(VenueData.C_ADDRESS) + "', " +
									jsonObj.getDouble(VenueData.C_LATITUDE) + ", " +
									jsonObj.getDouble(VenueData.C_LONGITUDE) + ", '" +
									jsonObj.getString(VenueData.C_PHONE_NUMBER) + "', '" +
									jsonObj.getString(VenueData.C_SITE) + "', '" +
									jsonObj.getString(VenueData.C_IMAGE) + "'";
                    
         					db.execSQL(query);
             			}
             			cursor.close();
                	 }
                 }
                 edit.putLong("dbVersion", externalTimestamp);
                 edit.commit();
             }
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
						
	}
}
